package game.tileMap.model
{
	import com.adobe.utils.ArrayUtil;
	
	import game.tileMap.model.vo.BaseItem;
	import game.tileMap.model.vo.Skill;
	import game.tileMap.model.vo.UsableItem;
	
	import mx.logging.LogLogger;
	


	public class BattleFormula
	{
		public function BattleFormula()
		{
		}
		
		/**
		 *  计算最後命中率
		 *  @param user 使用者 @param target 目标
		 *  @param obj 使用的技能或物品(普通攻击时为nil)
		 */
		private function calc_hit(user:Battler, obj : BaseItem = null):Number{
			var hit:Number;
			var physical:Boolean;
			 if (obj == null ){
			 	 hit = user.hit   ; 
			 	 trace("获取命中率"+user.hit)                    // 获取命中率
     			 physical = true;
			 } else if(obj is Skill){
			 	//技能攻击
			 	var skill:Skill=obj as Skill;
			 	 hit = skill.hit ;                       // 获取命中率
     			physical = skill.physical_attack;
			 }  else{
			 	//物品攻击
			 //	var item:Item=obj as Skill;
			 //	 hit = 100                             //设命中率为100％
      		//	physical = obj.physical_attack
			 }                          
		     
		   //物理攻击
		    if (physical ){
		    	//hit /= 4 if user.reduce_hit_ratio?    // 中了暗黑状态时命中率降低为25％
		    }                            
   			 return hit;
 
		}
   
   
   		/**
		 *  计算最後闪躲率
		 *  @param user 使用者 @param target 目标
		 *  @param obj 使用的技能或物品(普通攻击时为nil)
		 */
   		private function calc_eva(user:Battler, target:Battler,obj : BaseItem = null):Number{
			var eva:Number;
			 eva = target.eva; 
			   if ( obj != null ){
			   	 // 当obj为物品或技能,非物理攻击时闪躲率 0%
			  	// if (!obj.physical_attack)		   	
			   	// 	eva = 0  ;
			   }  		
			   //  无法闪躲的场合, 闪躲率为 0%
			   if ( target.parriable){
			    	 eva = 0  ;
			   }                      
			 return eva;
 
		}
   
		private  function make_attack_damage_value(attacker:Battler, target : Battler):void{
			var damage:Number = attacker.atk  - target.def         //基础计算
		   	damage < 0 ? damage=0:null;                        // 设负数伤害为 0
			// 属性校正
		  // damage *= elements_max_rate(attacker.element_set)   
		   //damage /= 100;
		    // 若伤害为 0 一半机率伤害为1
		    if (damage == 0 ){
		    	damage =Math.random()*2;
		    }else if(damage>0){
		    //	target.critical = (rand(100) < attacker.cri)        # 会心一击判断
		    // target.critical = false if prevent_critical         # 防止会心一击判断
		     // damage *= 3 if @critical                  
		    }                               
		   
		   // damage = apply_variance(damage, 20)             # 分散度
			// 防御校正
		    damage = target.apply_guard(damage)                   
		    target.actResult.hp_damage = damage       ;                     // 体力伤害
		}
		
		
		private function make_obj_damage_value(user:Battler,target:Battler, obj : UsableItem) : void {
			var damage:Number = obj.base_damage;                     //# 基础计算
		    if (damage > 0    ){			//若伤害为正
		    	damage += user.atk * 4 * obj.atk_f / 100     // # 使用者攻击力关系度
		      damage += user.spi * 2 * obj.spi_f / 100      //# 使用者精神力关系度
		      if (! obj.ignore_defense){	//# 除非无视防御力
		      	 damage -= target.def * 2 * obj.atk_f / 100    //# 目标攻击力关系度
		        damage -= target.spi * 1 * obj.spi_f / 100    //# 目标精神力关系度
		      }                     
		       
		     
		      	damage < 0 ? damage=0:null;           	// # 设负数伤害为0
		    }else if (damage < 0){
		    	damage -= user.atk * 4 * obj.atk_f / 100     // # 使用者攻击力关系度
		      	damage -= user.spi * 2 * obj.spi_f / 100     // # 使用者精神力关系度
		    }                           
		                
		  
		    damage *= elements_max_rate(obj.element_set,target)    //属性校正
		    damage /= 100;
		    // 分散度
			damage = target.apply_variance(damage, obj.variance)  	
			damage = target.apply_guard(damage)   
		    if (obj.damage_to_mp){
		    	target.actResult.mp_damage = damage   ;			// # 伤害魔力
		    }else{
		    	target.actResult.hp_damage = damage  ;    // # 伤害体力
		    }  
		                             
		 
		}
   		
		private function elements_max_rate(element_set:Array,target:Battler):int
		{
			if (element_set==null||element_set.length==0){
				return 100;
			}
			var rateMax:int=-1000;
			for (var i:int=0; i<element_set.length;i++){
				var elementId:int=element_set[i];
			//	trace("属性有效度:"+rateMax)
				var rate:int=target.getElementRate(elementId);
				if (rateMax<rate){
					rateMax=rate;
				}
			}
			trace("最大属性有效度:"+rateMax)
			return rateMax;
		}		
		
		
		
		private function execute_damage(user:Battler,target:Battler):void{
			//trace("受到伤害："+target.actResult.hp_damage)
			if (target.actResult.hp_damage > 0  ){
				//攻击移除状态
				target.remove_states_shock();      
			}        
		     
		   
		    target.hp -= target.actResult.hp_damage;
		    target.mp -= target.actResult.mp_damage;
		    if (target.actResult.absorbed ){            // 若吸收
		      user.hp += target.actResult.hp_damage
		      user.mp += target.actResult.mp_damage
		    }
		}
    
		/**
		 * 计算攻击效果
		 * @param attacker 攻击者 @param target 攻击目标
		 */
		public  function attackEffect(attacker : Battler, target : Battler):void{
			target.clear_action_results();
			 //unless attack_effective?(attacker)
		     // @skipped = true
		     // return
		   
//		    if (Math.random()*100 >= calc_hit(attacker) ){
//		    	// 计算命中率
//		    	trace("MISS命中率"+calc_hit(attacker))
//		    	 target.actResult.missed = true;
//		     	 return;
//		    }           
//		     	    
//		    if (Math.random()*100 < calc_eva(attacker,target) ){//            # 计算闪躲率
//		      target.actResult.evaded = true;
//		      trace("避开了"+calc_eva(attacker,target))
//		      return;
//		    }
		    make_attack_damage_value(attacker, target)    ;        ///# 计算伤害
		    execute_damage(attacker,target);                      ///# 伤害效果
		    if (target.actResult.hp_damage == 0 ){
		    	 return ;
		    }                           //# 判断是否有物理伤害
		                                        
		   
//		    apply_state_changes(attacker)                // 增减状态
		 
		
		}
    
   
   		public  function skillEffect(user: Battler,target : Battler, skill:Skill) : void {
			target.clear_action_results();
			
			 if (Math.random()*100 >= calc_hit(user) ){
		    	// 计算命中率
		    	
		    	
		    	 target.actResult.missed = true;
		     	 return;
		    }           
		     	    
		    if (Math.random()*100 < calc_eva(user,target) ){//            # 计算闪躲率
		      target.actResult.evaded = true;
		    
		      return;
		    }
		    
			make_obj_damage_value(user, target,skill)    ;        ///# 计算伤害
		    execute_damage(user,target);                      ///# 伤害效果
		    if (target.actResult.hp_damage == 0 ){
		    	 return ;
		    }     
			 apply_state_changes(target,skill)  ; 
		}
   
		
		
	
		
		//状态变化
		public function apply_state_changes(target:Battler,obj:UsableItem=null):void{
			var plus:Array=obj.plus_state_set 
			var minus:Array=obj.minus_state_set 
			
				var added_arr:Array=target.addedStateId_arr;
				var removed_arr:Array=target.removedStateId_arr;
			for each (var i:int in plus){
				if (target.hasState(i)){
					target.remainedStateId_arr.push(i)         //记录为变更状态
					continue;
				}
				if (Math.random()*100 < 101) 
		       		target.add_state(i)                     
		        	added_arr.push(i)  
				}
			
			for each (var j:int in minus){
				if (target.hasState(j)){
					continue;
				}else{
					target.remove_state(i)                   // 移除状态
					removed_arr.push(i)  
				}
			}
			
			//保存附加和移除数组的交集
			var intersection:Array=[];
			
			if (added_arr.length>removed_arr.length){
				for each (var k:int in added_arr){
					if (ArrayUtil.arrayContainsValue(removed_arr,k)){
						intersection.push(k);
					}
				}
			}else{
				for each (var kk:int in removed_arr){
					if (ArrayUtil.arrayContainsValue(added_arr,kk)){
						intersection.push(kk);
					}
				}
			}
			
			//删除同时存在附加和移除中的状态ID
			for each (var ii:int in intersection){
				if (ArrayUtil.arrayContainsValue(added_arr,ii)&&ArrayUtil.arrayContainsValue(removed_arr,ii)){
					ArrayUtil.removeValueFromArray(added_arr,ii);
					ArrayUtil.removeValueFromArray(removed_arr,ii);
				}
			}
			
		}
	}
}